package org.swidgets.sinputdata;

import java.util.Date;

import org.swidgets.base.slabel.SLabel;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.ChangeListenerCollection;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.MouseListener;
import com.google.gwt.user.client.ui.PopupListener;
import com.google.gwt.user.client.ui.PopupListenerCollection;
import com.google.gwt.user.client.ui.SourcesChangeEvents;
import com.google.gwt.user.client.ui.SourcesPopupEvents;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class CalendarWidget extends Composite implements ClickListener,
		SourcesChangeEvents , SourcesPopupEvents {

	private String[] years = new String[] { "1999", "2000", "2001",
			"2002", "2003", "2004", "2005", "2006","2007"};

	private class NavBar extends Composite implements ClickListener {


		public final DockPanel bar = new DockPanel();
		public final HistorableButton prevMonth = new HistorableButton("<-", this, Utilita.getNameMonths());
		public final HistorableButton prevYear = new HistorableButton("<<", this,years);
		public final HistorableButton nextYear = new HistorableButton(">>", this,years);
		public final HistorableButton nextMonth = new HistorableButton("->", this, Utilita.getNameMonths());
		public final Button oggi = new Button("Oggi",this);
		
		
		private final CalendarWidget calendar;
		
		public NavBar(CalendarWidget calendar) {
			this.calendar = calendar;

			initWidget(bar);
			bar.setStyleName("CalendarHeader");


			HorizontalPanel prevButtons = new HorizontalPanel();
			prevButtons.add(prevYear);
			prevButtons.add(prevMonth);			
			HorizontalPanel nextButtons = new HorizontalPanel();
			nextButtons.add(nextMonth);
			nextButtons.add(nextYear);

			bar.add(prevButtons, DockPanel.WEST);
			bar.setCellHorizontalAlignment(prevButtons, DockPanel.ALIGN_LEFT);
			bar.add(nextButtons, DockPanel.EAST);
			bar.setCellHorizontalAlignment(nextButtons, DockPanel.ALIGN_RIGHT);
			bar.add(oggi, DockPanel.CENTER);
			oggi.setWidth("100%");
			bar.setCellHorizontalAlignment(oggi, DockPanel.ALIGN_CENTER);
			bar.setCellWidth(oggi, "100%");
//			prevYear.setStyleName("calendarButtonGrigioScuro");
//			prevMonth.setStyleName("calendarButtonGrigioScuro");
//			nextMonth.setStyleName("calendarButtonGrigioScuro");
//			nextYear.setStyleName("calendarButtonGrigioScuro");
//			oggi.setStyleName("calendarButtonGrigioScuro");
		}

		public void onClick(Widget sender) {
			if (sender == oggi) {
				dataOdierna();
			}
			else
			{
				HistorableButton Hsender = (HistorableButton)sender;
				if (Hsender == prevMonth) {
					if (Hsender.getStatus()==Hsender.CLICKED)
					{
						calendar.prevMonth();
					}
					else
					{
						goMonth(Hsender.getSelectedIndex());
					}
				} else if (sender == nextMonth) {
					if (Hsender.getStatus()==Hsender.CLICKED)
					{
						calendar.nextMonth();
					}
					else
					{
						goMonth(Hsender.getSelectedIndex());
					}
				} else if ( sender == prevYear ){
					if (Hsender.getStatus()==Hsender.CLICKED)
					{
						calendar.prevYear();
					}
					else
					{
						goYear(Hsender.getSelectedIndex());
					}

				} else if (sender == nextYear) {
					if (Hsender.getStatus()==Hsender.CLICKED)
					{
						calendar.nextYear();
					}
					else
					{
						goYear(Hsender.getSelectedIndex());
					}
				}
			}
		}
	}

	private class NavBar2 extends Composite implements ClickListener {

		public final DockPanel bar2 = new DockPanel();
		public final Button chiudi = new Button("X",this);
		public final Button info = new Button("?", this);

		public final SLabel title = new SLabel();

		private final CalendarWidget calendar;

		public NavBar2(CalendarWidget calendar) {
			this.calendar = calendar;

			initWidget(bar2);
			bar2.setStyleName("navbar2");
			title.setStyleName("smallTitle");

			bar2.add(info, DockPanel.WEST);
			bar2.setCellHorizontalAlignment(info, DockPanel.ALIGN_LEFT);
			bar2.add(title, DockPanel.CENTER);
			bar2.setVerticalAlignment(DockPanel.ALIGN_MIDDLE);
			bar2.setCellHorizontalAlignment(title, HasAlignment.ALIGN_CENTER);
			bar2.setCellVerticalAlignment(title, HasAlignment.ALIGN_MIDDLE);
			bar2.setCellWidth(title, "100%");
			bar2.add(chiudi, DockPanel.EAST);
			bar2.setCellHorizontalAlignment(chiudi, DockPanel.ALIGN_RIGHT);

			//info.setStyleName("calendarButtonGrigioChiaro");
			//chiudi.setStyleName("calendarButtonGrigioChiaro");
			info.setWidth("20px");
			chiudi.setWidth("20px");

		}

		public void onClick(Widget sender) {
			if (sender == info) {
				Window.alert("Selezione della data:\n- usa i bottoni << >> per seleziona l'anno;\n- usa i bottoni <- -> per selezionare il mese.");
			}else if(sender == chiudi){
				closeCalendar();
			}
		}
	}
	private class NavBar3 extends Composite implements ClickListener {

		public final DockPanel bar2 = new DockPanel();

		public final HTML title = new HTML();

		private final CalendarWidget calendar;

		public NavBar3(CalendarWidget calendar) {
			this.calendar = calendar;

			initWidget(bar2);
			bar2.setStyleName("navbar2");
			title.setStyleName("smallTitle");

			bar2.add(title, DockPanel.CENTER);
			bar2.setVerticalAlignment(DockPanel.ALIGN_MIDDLE);
			bar2.setCellHorizontalAlignment(title, HasAlignment.ALIGN_CENTER);
			bar2.setCellVerticalAlignment(title, HasAlignment.ALIGN_MIDDLE);
			bar2.setCellWidth(title, "100%");

		}

		public void onClick(Widget sender) {

		}
	}
	private static class CellHTML extends HTML {
		private int day;

		public CellHTML(String text, int day) {
			super(text);
			this.day = day;
		}

		public int getDay() {
			return day;
		}
	}

	private ChangeListenerCollection changeListeners;
	private PopupListenerCollection  popUpListeners;

	private final NavBar navbar = new NavBar(this);
	private final NavBar2 navbar2 = new NavBar2(this);
	private final NavBar3 navbar3 = new NavBar3(this);
	private final DockPanel outer = new DockPanel();

	private final Grid grid = new Grid(7, 7) {
		public boolean clearCell(int row, int column) {
			boolean retValue = super.clearCell(row, column);

			Element td = getCellFormatter().getElement(row, column);
			DOM.setInnerHTML(td, "");
			return retValue;
		}
	};

	private Date date = new Date();

	public CalendarWidget() {
		initWidget(outer);
		VerticalPanel vp = new VerticalPanel();
		vp.add(navbar2);
		vp.add(navbar);
		vp.setWidth("100%");
		vp.setStyleName("CalendarHeader");
		outer.add(vp, DockPanel.NORTH);
		outer.setCellWidth(vp, "100%");

		VerticalPanel vp2 = new VerticalPanel();
		vp2.add(grid);
		vp2.add(navbar3);
		vp2.setWidth("100%");

		outer.add(vp2, DockPanel.CENTER);
//		drawCalendar();
		//setStyleName("CalendarWidget");
	}

	
	
	public void drawCalendar() {
		final int appoggioAnno;
		final int appoggioMese;
		final int appoggioGiorno2;
		int year = getYear();
		int month = getMonth();
		int day = getDay();
		appoggioAnno = year;
		appoggioMese = month;
		appoggioGiorno2 = day;
		setHeaderText(year, month);
		setFooterText(getYear(),getMonth(),getDay(),getDayName());
		grid.setStyleName("CalendarBody");
		grid.getRowFormatter().setStyleName(0, "smallTitle");
		for (int i = 0; i < Utilita.getNameDays().length; i++) {
			grid.getCellFormatter().setStyleName(0, i, "smallLabel");
			grid.setText(0, i, Utilita.getNameDay(i).substring(0, 3));
		}

		Date now = new Date();
		int sameDay = Utilita.getMonthDay(now);
		int today = (Utilita.getMonth(now) == month && Utilita.getYear(now) == year) ? sameDay
				: 0;

		int firstDay = Utilita.getWeekDay(Utilita.getDate(year, month, 1));
		int numOfDays = Utilita.getDaysInMonth(year, month);

		int j = 0;
		for (int i = 1; i < 7; i++) {
			for (int k = 0; k < 7; k++, j++) {
				int displayNum = (j - firstDay + 1);
				final int appoggioGiorno;
				appoggioGiorno = displayNum;
				if (j < firstDay || displayNum > numOfDays) {
					grid.getCellFormatter().setStyleName(i, k, "smallLabel");
					grid.setHTML(i, k, "&nbsp;");
				} else {
					final HTML html = new CellHTML("<span>"
							+ String.valueOf(displayNum) + "</span>",
							displayNum);
					html.addClickListener(this);

					grid.getCellFormatter().setStyleName(i, k, "smallLabel");
					grid.getCellFormatter().addStyleName(i, k, "NoBorderDay");
//					if (displayNum == today) {
//						grid.getCellFormatter().addStyleName(i, k, "today");
//					} else if (displayNum == sameDay) {
//						grid.getCellFormatter().addStyleName(i, k, "day");
//					}
					if (displayNum == day) {
						grid.getCellFormatter().setStyleName(i, k, "SelectedDay");
						//grid.getCellFormatter().addStyleName(i, k, "today");
					}

					html.addMouseListener(new MouseListener(){

						public void onMouseDown(Widget sender, int x, int y) {
						}

						public void onMouseEnter(Widget sender) {
							if(appoggioGiorno2!=appoggioGiorno){
								html.setStyleName("MouseDay");
							}
							setDate(appoggioAnno,appoggioMese,appoggioGiorno);

						}

						public void onMouseLeave(Widget sender) {
							if(appoggioGiorno2!=appoggioGiorno){
								html.setStyleName("NoMouseDay");
							}
						}

						public void onMouseMove(Widget sender, int x, int y) {
						}

						public void onMouseUp(Widget sender, int x, int y) {;
						}

					});
					grid.setWidget(i, k, html);
				}

			}
		}
	}

	protected void setHeaderText(int year, int month) {
		navbar2.title.setText(Utilita.getNameMonth(month) + ", " + year);
	}
	protected void setFooterText(int year, int month,int day,int dayName) {
		navbar3.title.setText(day+ " " +Utilita.getNameMonth(month) + " " + year + ", " + Utilita.getNameDay(dayName));
	}
	protected void setHistoryButton(int year, int month) {
		navbar.prevMonth.setSelectedIndex(month);
		navbar.nextMonth.setSelectedIndex(month);

		int index = year-1999;
		if (index>=0)
		{
			navbar.prevYear.setSelectedIndex(index);
			navbar.nextYear.setSelectedIndex(index);
		}
	}

	private void closeCalendar()
	{
		popUpListeners.firePopupClosed(null, false);
	}

	public void prevMonth() {
		int month = getMonth() - 1;
		if (month < 0) {
			setDate(getYear() - 1, 11, getDay());
		} else {
			setMonth(month);
		}
		drawCalendar();
	}

	public void nextMonth() {
		int month = getMonth() + 1;
		if (month > 11) {
			setDate(getYear() + 1, 0, getDay());
		} else {
			setMonth(month);
		}
		drawCalendar();
	}

	public void goMonth(int month)
	{
		setMonth(month);
		drawCalendar();
	}

	public void prevYear() {
		setYear(getYear() - 1);
		drawCalendar();
	}

	public void nextYear() {
		setYear(getYear() + 1);
		drawCalendar();
	}

	public void goYear(int yearIndex)
	{
		setYear(1999+yearIndex);
		drawCalendar();
	}

	public void setDate(int year, int month, int day) {
		date = Utilita.getDate(year, month, day);
		//setFooterText(getYear(),getMonth(),getDay(),getDayName());
		setHistoryButton(getYear(),getMonth());
	}
	public void setDate(Date data) {
		date =data;
		//setFooterText(getYear(),getMonth(),getDay(),getDayName());
		setHistoryButton(getYear(),getMonth());
	}

	public void setYear(int year) {
		Utilita.setYear(date, year);
		setHistoryButton(getYear(),getMonth());
	}

	public void setMonth(int month) {
		Utilita.setMonth(date, month);
		setHistoryButton(getYear(),getMonth());
	}

	public int getYear() {
		return Utilita.getYear(date);
	}

	public int getMonth() {
		return Utilita.getMonth(date);
	}

	public int getDay() {
		return Utilita.getMonthDay(date);
	}
	public int getDayName() {
		return Utilita.getWeekDay(date);
	}
	public Date getDate() {
		return date;
	}

	public void onClick(Widget sender) {
		CellHTML cell = (CellHTML) sender;

		setDate(getYear(), getMonth(), cell.getDay());
		drawCalendar();

		if (changeListeners != null) {
			changeListeners.fireChange(this);
		}

	}


	public void addChangeListener(ChangeListener listener) {
		if (changeListeners == null)
			changeListeners = new ChangeListenerCollection();
		changeListeners.add(listener);
	}

	public void removeChangeListener(ChangeListener listener) {
		if (changeListeners != null)
			changeListeners.remove(listener);
	}

	public void addPopupListener(PopupListener listener) {
		if (popUpListeners == null)
			popUpListeners = new PopupListenerCollection();
		popUpListeners.add(listener);
	}

	public void removePopupListener(PopupListener listener) {
		if (popUpListeners == null)
			popUpListeners.remove(listener);
	}

	public void modificaData(int anno,int mese,int giorno){
		setDate(anno, mese, giorno);
		drawCalendar();
	}
	public void modificaDataDate(Date date){
		modificaData(Utilita.getYear(date), Utilita.getMonth(date), Utilita.getMonthDay(date));
	}
	public void dataOdierna(){
		date = new Date();
		setDate(Utilita.getYear(date), Utilita.getMonth(date), Utilita.getMonthDay(date));
		drawCalendar();
	}

}
